import * as net from "net"
import * as util from "../util";
import * as Service from "./Service";
const { v4: uuid } = require('uuid');

const handle: util.SocketServiceHandle = {
    login(socket: net.Socket, username: string) {
        // 去除首位空白字符
        username = username.trim();
        // 用户名为空
        if (username.length === 0) {
            socket.write(util.INVALID_USERNAME_MESSAGE);
            socket.end()
            return;
        }
        // 用户名已存在
        for (let user of Service.userList) {
            if (user.name === username) {
                socket.write(util.USERNAME_EXIST_MESSAGE);
                socket.end()
                return;
            }
        }
        // 用户已登录
        if (getCurrentUser(socket) !== null) {
            socket.write(util.USER_LOGGED_IN_MESSAGE);
            socket.end()
            return;
        }
        // 创建新用户
        let newUser: util.user = {
            name: username,
            socket: socket,
            id: generateUUID(),
            ip: socket.remoteAddress || 'unknown'
        }
        // 发送用户列表
        let allUser: util.UserInfo[] = []
        for (let user of Service.userList) {
            allUser.push({
                id: user.id,
                name: user.name,
                ip: user.ip
            })
        }
        socket.sendJSON(util.ResponseCommand.REMAIN_USER, allUser)
        // 广播新用户加入
        let newUserInfo: util.UserInfo = {
            id: newUser.id,
            name: newUser.name,
            ip: newUser.ip
        }
        broadcast(socket, util.ResponseCommand.NEW_USER, newUserInfo)
        // 加入用户列表
        Service.userList.push(newUser);
        util.logInConsole(`用户 ${newUser.name}(${newUser.ip}) 加入聊天室,id:${newUser.id}`);
    },

    logout(socket: net.Socket, data: unknown) {
        logout(socket)
    },

    say(socket: net.Socket, data: string) {
        // data为空
        if (data.length === 0) {
            return;
        }
        // 获取当前用户
        let currentUser: util.user | null = authUserLogin(socket)
        if (currentUser === null) {
            return;
        }
        // 广播消息
        let userChat: util.UserChat = {
            id: currentUser.id,
            message: data
        }
        broadcast(socket, util.ResponseCommand.USER_CHAT, userChat)
        util.logInConsole(`用户 ${currentUser.name} 发送消息: ${data}`);
    },

    whisper(socket: net.Socket, data: util.whisperMessage) {
        data.id = data.id.trim();
        data.message = data.message.trim();
        // 验证用户
        let currentUser: util.user | null = authUserLogin(socket)
        if (currentUser === null) {
            return
        }
        let targetUser: util.user | null = null;
        for (let user of Service.userList) {
            if (user.id === data.id) {
                targetUser = user
                break
            }
        }
        if (targetUser === null) {
            socket.write(util.USER_NOT_EXIST_MESSAGE)
            return
        }
        // 发送消息
        let whisper: util.whisperMessage = {
            id: currentUser.id,
            message: data.message,
        }
        targetUser.socket.sendJSON(util.ResponseCommand.USER_WHISPER, whisper)
    },

    end: (socket: net.Socket) => {
        let user: util.user | null = getCurrentUser(socket)
        if (user) {
            logout(socket)
        }
    }
}

handle.login.command = util.RequestCommand.LOGIN
handle.say.command = util.RequestCommand.SAY;
handle.whisper.command = util.RequestCommand.WHISPER
handle.logout.command = util.RequestCommand.LOGOUT
handle.logout.onError = true
handle.end.onEnd = true

export default handle;

function generateUUID(): string {
    const uid = uuid();
    return uid.replace(/-/g, '');
}

function getCurrentUser(socket: net.Socket): util.user | null {
    for (let user of Service.userList) {
        if (user.socket === socket) {
            return user;
        }
    }
    return null;
}

function authUserLogin(socket: net.Socket): util.user | null {
    let user = getCurrentUser(socket);
    if (user === null) {
        socket.write(util.USER_NOT_LOGIN_MESSAGE)
        socket.end()
    }
    return user;
}

function broadcast<T>(excludeSocket: net.Socket, command: util.ResponseCommand, data: T): void {
    Service.userList.forEach((client) => {
        if (client.socket !== excludeSocket) {
            let message: util.ResponseMessage<T> = {
                command: command,
                data: data
            }
            client.socket.write(JSON.stringify(message));
        }
    })
}

function logout(socket: net.Socket) {
    // 获取当前用户
    let currentUser: util.user | null = authUserLogin(socket)
    if (currentUser === null) {
        return;
    }
    // 广播消息
    broadcast(socket, util.ResponseCommand.LOGOUT_USER, currentUser.id)
    // 从用户列表中移除
    for (let i = 0; i < Service.userList.length; i++) {
        if (Service.userList[i].socket === socket) {
            Service.userList.splice(i, 1);
            break
        }
    }
    util.logInConsole(`用户 ${currentUser.name}(${currentUser.ip}) 退出聊天室`);
}